package top.hmtools.javaWeb.userAgent;

/**
 * Container class for user-agent information with operating system and browser details. 
 * Can decode user-agent strings.
 * <br><br>
 * Resources:<br>
 * <a href="http://www.useragentstring.com">User Agent String.Com</a><br>
 * <a href="http://www.user-agents.org">List of User-Agents</a><br>
 * <a href="http://www.zytrax.com/tech/web/browser_ids.htm">Browser ID (User-Agent) Strings</a><br>
 * <a href="http://www.zytrax.com/tech/web/mobile_ids.html">Mobile Browser ID (User-Agent) Strings</a><br>
 * <a href="http://www.joergkrusesweb.de/internet/browser/user-agent.html">Browser-Kennungen</a><br>
 * <a href="http://deviceatlas.com/devices">Device Atlas - Mobile Device Intelligence</a><br>
 * <a href="http://mobileopera.com/reference/ua">Mobile Opera user-agent strings</a><br>
 * <a href="http://en.wikipedia.org/wiki/S60_platform">S60 platform</a><br>
 * <a href="http://msdn.microsoft.com/en-us/library/ms537503.aspx">Understanding User-Agent Strings</a><br>
 * <a href="http://developer.sonyericsson.com/site/global/docstools/browsing/p_browsing.jsp">Sony Ericsson Web Docs & Tools</a><br>
 * <a href="http://developer.apple.com/internet/safari/faq.html#anchor2">What is the Safari user-agent string</a><br>
 * <a href="http://www.pgts.com.au/pgtsj/pgtsj0208c.html">List of User Agent Strings</a><br>
 * <a href="http://blogs.msdn.com/iemobile/archive/2006/08/03/Detecting_IE_Mobile.aspx">Detecting Internet Explorer Mobile's User-Agent on the server</a>
 */

/**
 * @author harald
 *
 */
public class UserAgentTools
{
	
	private OperatingSystem operatingSystem = OperatingSystem.UNKNOWN;
	private Browser browser = Browser.UNKNOWN;
	private int id;
	private String userAgentString;
		
	/**
	 * 构造函数。
	 * <br>根据操作系统（枚举），浏览器（枚举）初始化userAgentTools（useragent信息）对象实例
	 * @param operatingSystem
	 * @param browser
	 */
	public UserAgentTools(OperatingSystem operatingSystem, Browser browser)
	{
		this.operatingSystem = operatingSystem;
		this.browser = browser;
		this.id = (( operatingSystem.getId() << 16) + browser.getId());
	}
	
	/**
	 * 构造函数。
	 * <br>根据userAgent字符串（从HTTP header信息中提取）
	 * @param userAgentString
	 */
	public UserAgentTools(String userAgentString)
	{
		Browser browser = Browser.parseUserAgentString(userAgentString);
		
		OperatingSystem operatingSystem = OperatingSystem.UNKNOWN;
		
		// BOTs don't have an interesting OS for us
		if (browser != Browser.BOT)
			operatingSystem = OperatingSystem.parseUserAgentString(userAgentString);
		
		this.operatingSystem = operatingSystem;
		this.browser = browser;
		this.id = (( operatingSystem.getId() << 16) + browser.getId());
		this.userAgentString = userAgentString;
	}

	
	/**
	 * 根据userAgent字符串（从HTTP header信息中提取）获取userAgentTools（useragent信息）对象实例
	 * @param userAgentString
	 * @return UserAgent
	 */
	public static UserAgentTools parseUserAgentString(String userAgentString) {		
		return new UserAgentTools(userAgentString);
	}
	

	/**
	 * 获取浏览器版本信息
	 * <br>必须在执行 UserAgent(String) 或者 UserAgent.parseUserAgent(String)后使用。 
	 * <br>如果没有可用的信息，会返回null
	 * @return Version
	 */
	public Version getBrowserVersion() {
		return this.browser.getVersion(this.userAgentString);
	}
	
	/**
	 * 获取客户端操作系统信息
	 * <br>必须在执行 UserAgent(String) 或者 UserAgent.parseUserAgent(String)后使用。 
	 * <br>如果没有可用的信息，会返回null
	 * @return the system
	 */
	public OperatingSystem getOperatingSystem() {
		return operatingSystem;
	}

	/**
	 * 获取客户端浏览器信息
	 * <br>必须在执行 UserAgent(String) 或者 UserAgent.parseUserAgent(String)后使用。 
	 * <br>如果没有可用的信息，会返回null
	 * @return the browser
	 */
	public Browser getBrowser() {
		return browser;
	}

	/**
	 * Returns an unique integer value of the operating system & browser combination
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * Combined string representation of both enums
	 */
	public String toString() {
		return this.operatingSystem.toString() + "-" + this.browser.toString();
	}
	
	/**
	 * Returns UserAgent based on specified unique id
	 * @param id
	 * @return
	 */
	public static UserAgentTools valueOf(int id)
	{
		OperatingSystem operatingSystem = OperatingSystem.valueOf((short) (id >> 16));
		Browser browser = Browser.valueOf( (short) (id & 0x0FFFF));
		return new UserAgentTools(operatingSystem,browser);
	}
	
	/**
	 * Returns UserAgent based on combined string representation
	 * @param name
	 * @return
	 */
	public static UserAgentTools valueOf(String name)
	{
		if (name == null)
            throw new NullPointerException("Name is null");
		
		String[] elements = name.split("-");
		
		if (elements.length == 2)
		{
			OperatingSystem operatingSystem = OperatingSystem.valueOf(elements[0]);
			Browser browser = Browser.valueOf(elements[1]);
			return new UserAgentTools(operatingSystem,browser);
		}
		
		throw new IllegalArgumentException(
	            "Invalid string for userAgent " + name);
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((browser == null) ? 0 : browser.hashCode());
		result = prime * result + id;
		result = prime * result
				+ ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final UserAgentTools other = (UserAgentTools) obj;
		if (browser == null) {
			if (other.browser != null)
				return false;
		} else if (!browser.equals(other.browser))
			return false;
		if (id != other.id)
			return false;
		if (operatingSystem == null) {
			if (other.operatingSystem != null)
				return false;
		} else if (!operatingSystem.equals(other.operatingSystem))
			return false;
		return true;
	}	
	
}
